﻿using System.Collections.Generic;
using System.Drawing;
using System.Runtime.Versioning;

#pragma warning disable IDE0130 // 命名空间与文件夹结构不匹配
namespace zykControl
#pragma warning restore IDE0130 // 命名空间与文件夹结构不匹配
{

    /// <summary>
    /// 表示zykHFGrid控件的一个区,一区内可包含若干行
    /// </summary>
    /// <remarks></remarks>
    [SupportedOSPlatform("windows")]
    public class ZykHFGridArea
    {
        internal ZykHFGridArea(ZykHFGridRoot theBody, string theKey, int theIndex, Point theLocation)
        {
            Body = theBody;
            Key = theKey;
            Index = theIndex;
            Columns = theBody.Columns;
            if (Index / 2 * 2 == Index)
                BackColor = theBody.BackColorDouble;
            else
                BackColor = theBody.BackColorSingle;
            Location = theLocation;
        }

        public readonly ZykHFGridColumns Columns;
        public readonly ZykHFGridRoot Body;
        private readonly List<ZykHFGridRow> mRows = [];

        /// <summary>
        /// 返回此区中的行数
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int Count
        => mRows.Count;

        /// <summary>
        /// 检索此区包含的行
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public ZykHFGridRow this[int RowIndex]
        {
            get
            {
                return mRows[RowIndex];
            }
        }

        public ZykHFGridRow? FindRow(string theText, int theCellIndex)
        {
            if (theCellIndex > 0 | theCellIndex > Columns.Count - 1) return null;

            for (int xx = 0, loopTo = Count - 1; xx <= loopTo; xx++)
            {
                if ((this[xx][theCellIndex].Text ?? "") == (theText ?? "")) return this[xx];
            }

            return null;
        }

        public ZykHFGridRow AddRow(string[] theText)
        {
            var dItem = new ZykHFGridRow(this, mRows.Count, theText);
            mRows.Add(dItem);
            dItem.CellSelectChanged += OnCellSelectChanged;
            RawCountChanged?.Invoke();
            return dItem;
        }

        public ZykHFGridRow AddRow()
        {
            var dItem = new ZykHFGridRow(this, mRows.Count);
            mRows.Add(dItem);
            dItem.CellSelectChanged += OnCellSelectChanged;
            RawCountChanged?.Invoke();
            return dItem;
        }

        /// <summary>
        /// 行数量改变时发生
        /// </summary>
        /// <remarks></remarks>
        public event RawCountChangedEventHandler? RawCountChanged;

        public delegate void RawCountChangedEventHandler();

        public Color BackColor;

        /// <summary>
        /// 返回本区在数据集合当中的索引
        /// </summary>
        /// <remarks></remarks>
        public readonly int Index;
        public readonly string Key;

        /// <summary>
        /// 当前行改变后发生
        /// </summary>
        /// <remarks></remarks>
        public event RowSelectChangedEventHandler? RowSelectChanged;

        public delegate void RowSelectChangedEventHandler(ZykHFGridRow? theCell);

        /// <summary>
        /// 用于改变选中的单元格时发生的事件处理
        /// </summary>
        /// <param name="theItem"></param>
        /// <remarks></remarks>
        private void OnCellSelectChanged(ZykHFGridCell? theItem)
        {
            if (theItem == null) return;
            SelectedRowIndex = theItem.Row.Index;
            CellSelectChanged?.Invoke(theItem);
        }

        /// <summary>
        /// 当前单元格改变后发生
        /// </summary>
        /// <remarks></remarks>
        public event CellSelectChangedEventHandler? CellSelectChanged;

        public delegate void CellSelectChangedEventHandler(ZykHFGridCell theCell);

        /// <summary>
        /// 重画本区域
        /// </summary>
        /// <param name="theGraphics">绘图类</param>
        /// <param name="theClipRect">更新区域</param>
        /// <remarks></remarks>
        public void PaintRow(Graphics theGraphics, Rectangle theClipRect)
        {
            if (Count == 0)
                return;
            var meRect = new Rectangle(X - Body.XOffset, Y - Body.YOffset, Width, Height);
            if (theClipRect.IntersectsWith(meRect) == false)
                return;
            bool dIsSelect = IsSelected;
            Pen dAreaPen;
            Pen dAreaBorderPen;
            Font dFont;
            if (dIsSelect == true)
            {
                dAreaPen = new Pen(Body.SelectedRowBgColor);
                dAreaBorderPen = new Pen(Body.BorderColorSelected);
                dFont = Body.FontSelected;
            }
            else
            {
                dAreaPen = new Pen(BackColor);
                dAreaBorderPen = new Pen(Body.BorderColor);
                dFont = Body.Font;
            }

            for (int xx = 0, loopTo = Columns.Count - 1; xx <= loopTo; xx++)
            {
                var dCol = Columns[xx];
                if (Columns[xx].Visible == false)
                    continue;
                if (Columns[xx].IsBill == true)
                {
                    var dCell = this[0][dCol.Index];
                    var dRect = new Rectangle(dCell.X - Body.XOffset, dCell.Y - Body.YOffset, dCell.Width, dCell.Height);
                    Pen dPen;
                    if (dCell.IsSelected == true)
                    {
                        dPen = new Pen(Body.SelectedCellBgColor);
                    }
                    else if (dIsSelect == true)
                    {
                        dPen = dAreaPen;
                    }
                    else
                    {
                        dPen = new Pen(dCell.BackColor);
                    }

                    theGraphics.FillRectangle(dPen.Brush, dRect);
                    theGraphics.DrawString(dCell.Text, dFont, new SolidBrush(dCell.ForeColor), dRect, dCol.ItemFormat);
                    theGraphics.DrawLine(dAreaBorderPen, dRect.X, dRect.Bottom - 1, dRect.Right - 1, dRect.Bottom - 1);
                    theGraphics.DrawLine(dAreaBorderPen, dRect.Right - 1, dRect.Y, dRect.Right - 1, dRect.Bottom - 1);
                }
                else
                {
                    for (int yy = 0, loopTo1 = Count - 1; yy <= loopTo1; yy++)
                    {
                        var dCell = this[yy][dCol.Index];
                        var dRect = new Rectangle(dCell.X - Body.XOffset, dCell.Y - Body.YOffset, dCell.Width, dCell.Height);
                        Pen dPen;
                        if (dCell.IsSelected == true)
                        {
                            dPen = new Pen(Body.SelectedCellBgColor);
                        }
                        else if (dIsSelect == true)
                        {
                            dPen = dAreaPen;
                        }
                        else
                        {
                            dPen = new Pen(dCell.BackColor);
                        }

                        theGraphics.FillRectangle(dPen.Brush, dRect);
                        theGraphics.DrawString(dCell.Text, dFont, new SolidBrush(dCell.ForeColor), dRect, dCol.ItemFormat);
                        theGraphics.DrawLine(dAreaBorderPen, dRect.X, dRect.Bottom - 1, dRect.Right - 1, dRect.Bottom - 1);
                        theGraphics.DrawLine(dAreaBorderPen, dRect.Right - 1, dRect.Y, dRect.Right - 1, dRect.Bottom - 1);
                    }
                }
            }

            if (dIsSelect == true)
            {
                theGraphics.DrawLine(dAreaBorderPen, meRect.X, meRect.Y, meRect.Right - 1, meRect.Y);
                theGraphics.DrawLine(dAreaBorderPen, meRect.X, meRect.Y, meRect.X, meRect.Bottom - 1);
            }
        }

        public readonly Point Location = new();

        public int Width => Columns.Width;

        public int Height => ItemHeight * mRows.Count;

        public int X => Location.X;

        public int Y => Location.Y;

        public int ItemHeight => Body.ItemHeidht;

        public ZykHFGridRow? SelectedRow()
        {
            int dIndex = SelectedRowIndex;
            if (dIndex == -1) return null;

            return this[dIndex];
        }

        /// <summary>
        /// 如果本区被选中,返回True
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public bool IsSelected
        {
            get
            {
                if (Body.Count == 1) return true;
                if (Index == -1) return false;

                return Index == Body.SelectedAreaIndex;
            }
        }

        private int mSelectedRowIndex = -1;
        /// <summary>
        /// 返回/设置本区被选中的行
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public int SelectedRowIndex
        {
            get
            {
                if (IsSelected == false)
                {
                    return -1;
                }
                else if (mSelectedRowIndex < 0)
                {
                    if (Count > 0)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                }
                else if (mSelectedRowIndex > Count - 1)
                {
                    return Count - 1;
                }
                else
                {
                    return mSelectedRowIndex;
                }
            }

            set
            {
                if (value < -1)
                    value = -1;
                if (value > Count - 1)
                    value = Count - 1;
                bool dChange = value != SelectedRowIndex;
                if (dChange == false)
                    return;
                mSelectedRowIndex = value;
                if (value < 0)
                    Body.SelectedAreaIndex = -1;
                else
                    Body.SelectedAreaIndex = Index;
                if (value < 0)
                    RowSelectChanged?.Invoke(null);
                else
                    RowSelectChanged?.Invoke(this[value]);
                if (value >= 0 && SelectedRowIndex == -1)
                    this[value].SelectedCellIndex = 0;
            }
        }

        public void ToSelected()
        {
            Body.SelectedAreaIndex = Index;
        }
    }
}